package helper

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"zong-go/pkg/logger"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/url"
	"time"
)

// HttpOptions http请求参数
type HttpOptions struct {
	Header    map[string]interface{}
	Json      map[string]interface{}
	Query     map[string]interface{}
	Multipart struct {
		Name   string
		File   multipart.File
		Header *multipart.FileHeader
	}
}

// HttpRequest 发送http请求
func HttpRequest(method string, uri string, options HttpOptions) ([]byte, error) {
	// query 参数
	if len(options.Query) > 0 {
		// 拼接URL
		query := url.Values{}
		for key, value := range options.Query {
			query.Add(key, fmt.Sprintf("%v", value))
		}
		q := query.Encode()
		if len(q) > 0 {
			uri = uri + "?" + q
		}
	}

	// 超时10秒,并关闭ssh证书认证
	ts := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: ts,
		Timeout:   10 * time.Second,
	}

	// 文件上传 / json 参数
	var req *http.Request
	if len(options.Multipart.Name) > 0 {
		// 文件上传
		body := new(bytes.Buffer)
		writer := multipart.NewWriter(body)
		// 创建表单
		formFile, err := writer.CreateFormFile(options.Multipart.Name, options.Multipart.Header.Filename)
		logger.LogError(err)
		// 把上传文件转为byte,并放入表单里面
		_, err = io.Copy(formFile, options.Multipart.File)
		logger.LogError(err)
		err = writer.Close()
		logger.LogError(err)
		req, _ = http.NewRequest(method, uri, body)
		//req.Header.Set("Content-Type", "multipart/form-data; boundary="+multipart.NewWriter(body).Boundary())
		req.Header.Set("Content-Type", writer.FormDataContentType())
	} else {
		// json
		d, _ := json.Marshal(options.Json)
		body := bytes.NewBuffer(d)
		req, _ = http.NewRequest(method, uri, body)
		req.Header.Set("Content-Type", "application/json;charset=UTF-8")
	}

	if len(options.Header) > 0 {
		for key, value := range options.Header {
			req.Header.Set(key, fmt.Sprintf("%v", value))
		}
	}

	// 发起请求
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("Error: status code: %d", resp.StatusCode)
	}

	res, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	// 在循环里面使用 defer resp.Body.Close()，这是大忌。函数结束才会 Close
	//defer resp.Body.Close()
	err = resp.Body.Close()
	logger.LogError(err)

	//var result map[string]interface{}
	//err = json.Unmarshal(res, &result)
	//if err != nil {
	//	return nil, err
	//}

	return res, err
}
